package com.jt.www.common.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.jt.www.common.service.ContractService;
import com.jt.www.common.service.ZqService;
import com.jt.www.common.service.zqsign.dependency.ZQVO;
import com.jt.www.common.service.zqsign.param.agreement.Param;
import com.jt.www.dao.mapper.zq.ZqContractMapper;
import com.jt.www.exception.ParamException;
import com.jt.www.exception.ServiceException;
import com.jt.www.model.reps.GenericDataResponse;
import com.jt.www.model.zq.ZqContract;
import com.jt.www.model.zq.ZqParam;
import com.jt.www.model.zq.ZqVO;
import com.jt.www.remote.IdgClient;
import com.jt.www.util.CommonUtils;
import com.jt.www.util.insurancedata.ExcelUtil;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.regex.Pattern;


@Service
public class ContractServiceImpl implements ContractService {
    public static final Logger log = LoggerFactory.getLogger(ContractServiceImpl.class);

    private final static String BRANCH_CODE = "JT0114003";
    private final static String CONTRACT_NAME = "太原学平委托协议";
    @Value("${jtpf.zq.returnUrl}")
    public String returnUrl = "";

    @Value("${jtpf.zq.notifyUrl}")
    public String notifyUrl = "";

    @Value("${jtpf.zq.tNo}")
    public String tNo = "";

    @Value("${jtpf.zq.requestUrl}")
    public String requestUrl = "";

    @Value("${jtpf.zq.privateKey}")
    public String privateKey = "";

    @Value("${jtpf.zq.zqid}")
    public String zqid = "";

    @Value("${remote.edu_url}")
    public String eduUrl = "";

    @Autowired
    private ZqService zqService;
    @Autowired
    private IdgClient idgClient;
    @Autowired
    private ZqContractMapper zqContractMapper;

    private boolean isIDCard(String idCard) {
        String REGEX_ID_CARD = "(^[1-9]\\d{5}(18|19|([23]\\d))\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$)";
        return Pattern.matches(REGEX_ID_CARD, idCard);
    }

    private int getAgeByIDCard(String idCard) throws Exception {
        String birthday = "";
        if (idCard.length() == 18) {
            birthday = idCard.substring(6, 10) + "/"
                    + idCard.substring(10, 12) + "/"
                    + idCard.substring(12, 14);
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
        Date now = new Date();
        Date birth = sdf.parse(birthday);
        long intervalMilli = now.getTime() - birth.getTime();
        return (int) (intervalMilli / (24 * 60 * 60 * 1000)) / 365;
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public ResponseEntity<?> saveAgreement(Param agreement) throws Exception {
        //手机号正则表达式
        String regex = "^[1](([3|5|8][\\d])|([4][4,5,6,7,8,9])|([6][2,5,6,7])|([7][^9])|([9][1,8,9]))[\\d]{8}$";
        if (!CommonUtils.isMobiPhoneNum(regex, agreement.getPhoneNum())) {
            throw new ParamException("手机号不合法");
        }
        if (StringUtils.isEmpty(agreement.getCustName())) {
            throw new ParamException("姓名不能为空");
        }
        if (!isIDCard(agreement.getCardNo())) {
            throw new ParamException("身份账号不合法");
        }
        if (getAgeByIDCard(agreement.getCardNo()) < 18) {
            throw new ParamException("您需要填写投保人（家长）的姓名、身份证号，您当前填写的投保人不满18周岁，请修改");
        }
        ZqContract zqContract = agreement.getZqContract();

        ZQVO vo = createAgreement(agreement);
        String conAgreementNo = vo.getNo();
        zqContract.setContractNo(conAgreementNo);
        zqContract.setContractName(CONTRACT_NAME);
        zqContract.setProductCode("19PR999676");
        zqContract.setProductName("太原市学平乐专属保险");
        //创建html页面
        String responseText = zqService.createH5sgin(vo.getNo(), vo.getIdNo(), returnUrl, notifyUrl);
        log.info("responseText >>>>>>" + responseText);
        //返回签章页面
        JSONObject data = new JSONObject();
        data.put("responseText", responseText);
        data.put("no", conAgreementNo);

        Date date = new Date();
        //新增协议数据
        ZqContract zq = zqContractMapper.selectByUniquely(zqContract.getIdCardNo(), zqContract.getUserName(), zqContract.getBranchCode(), zqContract.getProductCode());
        if (zq != null) {
            zqContract.setId(zq.getId());
            zqContract.setUpdateTime(date);
            int i = zqContractMapper.updateByPrimaryKeySelective(zqContract);
            if (i < 1) {
                throw new ServiceException("委托人信息更新失败！");
            }
        } else {
            zqContract.setCreateTime(date);
            int i = zqContractMapper.insert(zqContract);
            if (i < 1) {
                throw new ServiceException("委托人信息保存失败！");
            }
        }
        return GenericDataResponse.okWithData(data);

    }

    @Override
    @Transactional(readOnly = true)
    public String contractFile(String userCode) {
        return zqContractMapper.selectPdfUrlByUserCodeAndBranchCode(userCode, BRANCH_CODE);
    }

    /**
     * 用户合同相关信息列表
     *
     * @param userCode
     * @return
     */
    @Override
    public List<ZqContract> contractFileList(String userCode) {
        List<ZqContract> zqContracts = zqContractMapper.selectByUserCode(userCode);
        if (zqContracts != null && !zqContracts.isEmpty()) {
            for (ZqContract zqContract : zqContracts) {
                String pdfUrl = null;
                try {
                    pdfUrl = zqService.getPdfUrl(zqContract.getContractNo());
                    zqContract.setContractUrl(pdfUrl);
                } catch (Exception e) {
                    log.error("无法获取合同url,原因:{}，合同号：{},身份证号：{}", e.getMessage(), zqContract.getContractNo(), zqContract.getIdCardNo());
                    zqContract.setContractUrl(null);
                }

            }
        }
        return zqContracts;
    }

    /**
     * 协议信息列表
     *
     * @param zqParam
     * @return
     */
    @Override
    public PageInfo<ZqVO> contractList(ZqParam zqParam) throws Exception {
        if (zqParam == null) {
            throw new Exception("请求参数不能为空");
        }
        if (StringUtils.isEmpty(zqParam.getProductCode())) {
            throw new Exception("产品编码不能为空");
        }
        return PageHelper.startPage(zqParam.getPageNum(), zqParam.getPageSize()).doSelectPageInfo(() -> zqContractMapper.selectByParam(zqParam));

    }

    /**
     * 协议信息列表
     *
     * @param zqParam
     * @return
     */
    @Override
    public void contractListByExcel(ZqParam zqParam, HttpServletResponse response) throws Exception {
        if (zqParam == null) {
            throw new Exception("请求参数不能为空");
        }
        if (StringUtils.isEmpty(zqParam.getProductCode())) {
            throw new Exception("产品编码不能为空");
        }
        zqParam.setPageNum(null);
        zqParam.setPageSize(null);
        long timeInMillis = Calendar.getInstance().getTimeInMillis();
        List<ZqVO> zqVOS = zqContractMapper.selectByParam(zqParam);
        //TODO 限制导出的最大数据条数
        ExcelUtil.exportExcel(zqVOS, "协议清单", "", ZqVO.class, String.valueOf(timeInMillis), response);
    }


    /**
     * 个人注册、创建合同、自动签章
     *
     * @param agreement
     * @return
     */
    @Override
    public ZQVO createAgreement(Param agreement) {
        //个人数字证书注册
        String regmsg = zqService.personReg(agreement.getCustName(), agreement.getCardNo(), agreement.getPhoneNum());
        JSONObject regjson = JSONObject.parseObject(regmsg);
        if (!regjson.getString("code").equals("0")) {
            if (regjson.getString("code").equals("120000")) {//user_code 已存在，无法推送
                zqService.updatePersonReg(agreement.getCustName(), agreement.getCardNo(), agreement.getPhoneNum());
            } else {
                throw new ServiceException(regjson.getString("msg"));
            }
        }
        //合同编码
        String conAgreementNo = String.valueOf(idgClient.nextId());
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        //TODO 给合同赋值
        ZQVO vo = agreement.getZQVO();
        vo.setNo(conAgreementNo);
        //江泰保险经纪股份有限公司太原小店营业部 编码
        vo.setSigner1(agreement.getCardNo());
        vo.setSigner2(BRANCH_CODE);
        vo.setName(CONTRACT_NAME);
        vo.setTno(tNo);
        vo.setSignDate(sdf.format(new Date()));
        //创建合同
        String cmsg = zqService.createContract(vo);
        JSONObject json = JSONObject.parseObject(cmsg);
        if (!json.getString("code").equals("0")) {
            if (json.getString("code").equals("120001")) {
                //如果合同已存在则撤销合同后再创建合同
                zqService.undoSign(conAgreementNo);
                return createAgreement(agreement);
            } else {
                throw new ServiceException(json.getString("msg"));
            }
        }
        //自动签章
        String signmsg = zqService.signAuto(vo.getNo(), vo.getSigner2());
        JSONObject jsons = JSONObject.parseObject(signmsg);
        if (!jsons.getString("code").equals("0")) {
            throw new ServiceException(jsons.getString("msg"));
        }
        return vo;
    }

    /**
     * 判断用户时候签署协议
     *
     * @return
     */
    @Override
    public String judgeIsSign(String idCode, String name) {
        String isSign = zqContractMapper.selectSignByUserCodeAndBranchCode(idCode, name, BRANCH_CODE);
        if (StringUtils.isEmpty(isSign)) {
            return "0";
        }
        return isSign;
    }

    /**
     * 定时更新协议失效状态
     * 规则：从签署开始 365天后 失效
     */
    @Override
    public void updateAgreementStatus() throws ParseException {
        Date date = new Date();
        //查询协议无效日期大于365的非无效数据
        List<ZqContract> zqContracts = zqContractMapper.selectByEfficacy();
        if (zqContracts != null && !zqContracts.isEmpty()) {
            for (ZqContract zqContract : zqContracts) {
                zqContract.setIsEfficacy("0");
                zqContract.setUpdateTime(date);
                zqContractMapper.updateByPrimaryKeySelective(zqContract);
            }
        }
    }

    /**
     * 更新合同状态 并添加合同号pdf url
     *
     * @param no
     * @return
     */
    @Override
    public String updateAgreement(String no) {
        ZqContract zqContract = zqContractMapper.selectByContractNo(no);
        if (zqContract != null) {
            try {
                String code = zqService.completionContract(no);
                //TODO 合同生效标记接口返回值处理
                log.info("合同生效标记接口返回：{}", code);
            } catch (IOException e) {
                e.printStackTrace();
            }
            Date date = new Date();
            zqContract.setIsEfficacy("1");
            zqContract.setIsSign("1");
            zqContract.setContractUrl(eduUrl + no);
            zqContract.setSignTime(date);
            zqContract.setUpdateTime(date);
            int i = zqContractMapper.updateByPrimaryKeySelective(zqContract);
            if (i < 1) {
                throw new ServiceException("异步回调接口更新协议信息失败");
            }
            return "success";
        }
        return "error";
    }


}
